home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / 16550.zip / FACT.C < prev    next >
Text File  |  1991-07-20  |  14KB  |  435 lines

  1. /*         FFFFFFF      A          CCCCCC    TTTTTTTTTTT            CCCCCC
  2.  *         F           A A        C               T                C
  3.  *         FFFFF      A   A       C               T                C
  4.  *         F         A AAA A      C               T                C
  5.  *         F        A       A     C               T       ..       C
  6.  *         F       A         A     CCCCCC         T       ..        CCCCCC
  7.  *
  8.  *            FACT.C -- FIFO Asynchronous Communication Test Program for
  9.  *                      NS16550 and NS16552 UARTs
  10.  *
  11.  *            Greg DeJager            Ver 1.0         1/31/89
  12.  *
  13.  *            Adapted from LBT.C -- LoopBack Test  Rev 1.1
  14.  *            Developed By:   Brian A. Berg
  15.  *                            Berg Software Design
  16.  *                            October 1988
  17.  *
  18.  */
  19.                
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <conio.h>
  23. #include <dos.h>
  24. #include "stdhdr.h"
  25. #include "serio.h"
  26.  
  27. /* define some macros for use herein */
  28. /*   program test name for user prompt and help screen */
  29. #define TESTNAME        "NS16550/NS16552 FIFO Asynchronous Communications Test (FACT)"
  30. /*   clear the RBR, LSR and IIR registers (used at start and before exit) */
  31. #define CLEAR_REGS()    ((void)rdRBR(), (void)rdRBR(), \
  32.              (void)rdLSR(), (void)rdIIR(), (void)wrMCR(0), \
  33.              (void)wrFCR(CLR_FIFO))
  34.  
  35. /*   GET ctrl-break/ctrl-c checking flag status via "INT 21H" */
  36. #define GETBRK()    (regs.h.ah = 0x33, regs.h.al = 0, \
  37.              intdos(®s, ®s), regs.h.dl)
  38. /*   SET ctrl-break/ctrl-c checking flag to argument via "INT 21H" */
  39. #define SETBRK(brk)    (regs.h.ah = 0x33, regs.h.al = 1, \
  40.              regs.h.dl = (brk), intdos(®s, ®s))
  41.  
  42. /* COMx-dependent parameters */
  43. UINT comvnum[COM_CNT] = {0x0C, 0x0B, 0x0B};        /* int. vector nos. for COMx */
  44. UINT uartbadd[COM_CNT] = {0x3F8, 0x2F8, 0x3220};   /* UART base adds. for COMx */
  45. UINT picmsk[COM_CNT] = {0xEF, 0xF7, 0xF7};         /* PIC masks for COMx: IRQ4,3 */
  46.  
  47. /* declare parameters and default values; override via invocation line args. */
  48. /*   argument 1: COM number */
  49. int com = COM_DEF;
  50. UINT ivnum;            /* int. vector number (set as comvnum[com-1]) */
  51. UINT ubase;            /* UART base address (set as uartbadd[com-1]) */
  52. /*   argument 2: baud rate divisor */
  53. int baudiv = BAUDIV_DEF;
  54.  
  55. UCHAR bytwr = 0;        /* write byte counter (goes from 0 to 255) */
  56. UCHAR bytrd = 0;        /* read byte counter (goes from 0 to 255) */
  57.  
  58. UCHAR iir, lsr;                 /* storage for IIR and LSR */
  59. UCHAR bytin;                    /* input byte storage */
  60.  
  61. UINT errflag = FALSE;           /* error indication and ID */
  62.  
  63. /* storage for original environment parameters */
  64. void far *savect;    /* interrupt vector */
  65. UCHAR savbrk;        /* ctrl-break flag */
  66. UINT savmsk;        /* PIC mask */
  67. UCHAR savier;        /* IER register */
  68. UCHAR savlcr;        /* LCR register */
  69. UCHAR savmcr;        /* MCR register */
  70. UCHAR savdll;        /* DLL register */
  71. UCHAR savdlm;        /* DLM register */
  72.  
  73. CNVTR cnvtr;            /* handy union for data type conversions */
  74. union REGS regs;        /* 16- and 8-bit registers for intdos() */
  75. int finit = FALSE;        /* boolean for program termination */
  76.  
  77. /* globals which control the tick mark on the screen */
  78. int tick = FALSE;        /* boolean for display of "tick" on CRT */
  79. int tick_ff = 0;        /* tick flip-flop (either 0 or 1) */
  80. int bytick = 0;            /* helps determine when to set tick boolean */
  81. UCHAR *tickstr[] = {"\b*", "\b$"};      /* "tick" mark strings */
  82.  
  83. /* Routines contained herein: */
  84. void main(int, char **);        /* main program */
  85. void interrupt far serint(void);    /* serial interrupt handler */
  86. void procarg(int, char **);        /* process invocation arguments */
  87. void savepar(void);            /* save our environment parameters */
  88. void rstrpar(void);            /* restore our environment parameters */
  89. void dspstr(UCHAR *);                   /* display a string to console */
  90. void usage(void);                       /* display usage info and exit */
  91.  
  92. /*
  93.  *    main(): main program
  94.  */
  95.  
  96. void main(argc, argv)
  97.    int argc;
  98.    char **argv;
  99. {
  100.     /* process invocation args., and set up int vector no. and UART base add */
  101.     procarg(argc, argv);    /* get com# and baudrate from argument string */
  102.     CLEAR_REGS();           /* clear RBR, LSR, IIR, MCR, and FIFOs */
  103.     savepar();              /* save our environment parameters */
  104.  
  105.     /* set baud rate */
  106.     wrLCR(0x80);                    /* set DLAB */
  107.     cnvtr.intval[0] = baudiv;
  108.     outp(DLL, cnvtr.chrval[0]);
  109.     outp(DLM, cnvtr.chrval[1]);
  110.     wrLCR(0x0B);                    /* 8 data, 1 stop, odd parity */
  111.  
  112.     printf("\n\n          %s\n\n",TESTNAME);    /*startup message*/
  113.  
  114.     /* wait loop to insure other machine has cleared its registers */
  115.     printf("\nHit a key when other program has been started.\n\n");
  116.     while( !(kbhit() && getch()) );
  117.  
  118.     /* set up registers for our environment */
  119.     wrFCR(CLR_FIFO);        /* clear transmitter and receiver FIFOs */
  120.     wrFCR(FIFO_EN);         /* enable FIFOs, set Rx trigger at 14 bytes */
  121.     if ( (rdIIR() & 0xc0) != 0xc0)          /* ensure FIFOs present */
  122.     {
  123.         printf("\nFatal Error.  FIFOs not present\n");
  124.         errflag = ENDPROG;
  125.     }
  126.     wrMCR(OUT2);            /* enable PIC interrupt (OUT2) */
  127.     wrIER(IER_VAL1);        /* Enable LSI and RDAI */
  128.     wrMCR(0x0a);            /* Assert RTS (and OUT2) */
  129.  
  130.     printf("Waiting for first 'Request To Send' from other machine...\n\n");
  131.     while (!(rdMSR() & CTS));     /* wait for other machine to assert RTS */
  132.  
  133.     printf("\n\nHit non-control key to stop:  ");
  134.  
  135.     /* Enable Tx interupts; loop until int. handler finished or any key struck */
  136.     wrIER(IER_VAL2);
  137.     while (!errflag)
  138.     {
  139.         if (kbhit() && getch())
  140.             errflag = ENDPROG;
  141.         if (tick)                       /* display tick mark */
  142.         {
  143.             /* display the tick mark */
  144.             printf("%s",tickstr[tick_ff]);
  145.             tick_ff = 1 - tick_ff;    /* update tick flip-flop */
  146.             tick = FALSE;
  147.         }
  148.     }
  149.     wrIER(0);                               /* disable UART interrupts */
  150.     while ( !(rdLSR() & TEMT) );            /* wait for Tx FIFO to clear */
  151.     CLEAR_REGS();   /* clear RBR, LSR, MCR and IIR registers before we exit */
  152.  
  153.     /* Output error message represented by 'errflag' variable */
  154.     switch (errflag)
  155.     {
  156.     case ENDPROG:           /* keyboard hit or fatal error */
  157.         break;
  158.  
  159.     case FALSEINT:          /* IIR shows no interrupt active */
  160.         printf("\nFalse interrupt.  No UART interrupt active.\n");
  161.         break;
  162.  
  163.     case STATUSERR:         /* Line Status interrupt generated */
  164.         printf("\nLine Status interrupt.  LSR = %x\n",lsr);
  165.         printf("Byte causing LSI = %x\n",bytin);
  166.         break;
  167.  
  168.     case MISMATCH:          /* Data received did not match data expected */
  169.         printf("\nData mismatch\n");
  170.         printf("Byte expected = %x\n",--bytrd);
  171.         printf("Byte received = %x\n",bytin);
  172.         break;
  173.  
  174.     case RX_ERROR:          /* RDAI generated but DR was not set */
  175.         printf("\nError: RDAI but no DR indication\n");
  176.         break;
  177.  
  178.     case TX_ERROR:          /* THREI generated but THRE was not set */
  179.         printf("\nError: THREI but no THRE indication\n");
  180.         break;
  181.  
  182.     case IIR_ERROR:         /* Invalid IIR */
  183.         printf("\nIIR invalid\n");
  184.         break;
  185.  
  186.     case TIMEOUT:           /* Character Timeout Interrupt */
  187.         printf("\nCharacter Timeout.\n");
  188.         break;
  189.  
  190.     case TIMEOUT_ERR:       /* False Character Timeout Interrupt */
  191.         printf("\nError: False Character Timeout Interrupt.\n");
  192.         break;
  193.  
  194.     default:
  195.         break;
  196.     }                       /* end of switch */
  197.  
  198.     rstrpar();              /* restore our environment parameters */
  199.  
  200.     printf("\n\n\nEnd of program; Environment parameters restored.\n");
  201.  
  202. }  /* end of main() */
  203.  
  204. /*
  205.  *    serint(): serial port interrupt handler
  206.  */
  207.  
  208. void interrupt far serint()
  209. {
  210.     int bytecnt=0;
  211.  
  212.     /* if errflag has been set, ignore the interrupt */
  213.     if (errflag)
  214.     {
  215.         wrIER(0);
  216.         outp(PICTRL, EOI);    /* send EOI to 8259A PIC */
  217.         return;
  218.     }
  219.  
  220.     /* here's the code to handle each of the various interrupt types */
  221.     switch (iir = rdIIR())
  222.     {
  223.     case F_NOIP:      /* NO Interrupt Pending */
  224.         errflag = FALSEINT;
  225.         break;
  226.  
  227.     case F_RLST:      /* Receiver Line STatus interrupt */
  228.         lsr = rdLSR();
  229.         bytin = rdRBR();        /* read byte with error */
  230.         errflag = STATUSERR;
  231.         break;
  232.  
  233.     case F_RDAV:      /* Received Data AVailable */
  234.         wrMCR(OUT2);            /* clear RTS */
  235.         lsr = rdLSR();
  236.         /* read bytes from FIFO and compare them with expected values */
  237.         while (rdLSR() & DR)
  238.         {
  239.             bytin = rdRBR();
  240.             if (bytin != bytrd++)
  241.             {
  242.                 errflag = MISMATCH;
  243.                 break;          /* error, stop reading FIFO */
  244.             }
  245.             else
  246.               /* display "tick" after reading 2560 bytes */
  247.                 if (!bytrd && ++bytick == 10)
  248.                 {
  249.                     bytick = 0;
  250.                     tick = TRUE;    /* turn on "tick" boolean */
  251.                 }
  252.         }
  253.         if (!errflag)
  254.             wrMCR(0x0a);         /* reassert RTS */
  255.         break;
  256.  
  257.     case F_IIR_THRE:  /* Transmitter Holding Register Empty */
  258.         lsr = rdLSR();
  259.         bytecnt = 0;
  260.         if (lsr & LSR_THRE)
  261.         {
  262.             while (rdMSR() & CTS)   /* while CTS, fill FIFO */
  263.                 if (bytecnt++ <= 15)
  264.                     wrTHR(bytwr++);
  265.                 else
  266.                     break;
  267.         }
  268.         else
  269.             errflag = TX_ERROR;     /* THREI without THRE set */
  270.         break;
  271.  
  272.     case F_CHR_TIMEOUT:       /* no characters received for 4 character times */
  273.         errflag = TIMEOUT;
  274.         if (rdLSR() & DR)
  275.             while (rdLSR() & DR)    /* clear all of FIFO */
  276.             {
  277.                 bytin = rdRBR();
  278.                 if (bytin != bytrd++)
  279.                 {
  280.                     errflag = MISMATCH;
  281.                     break;          /* error, stop reading FIFO */
  282.                 }
  283.             }
  284.         else
  285.             errflag = TIMEOUT_ERR;   /* false timeout interrupt */
  286.         break;
  287.  
  288.     default:    /* IIR default case: FATAL ERROR */
  289.         errflag = IIR_ERROR;
  290.         break;
  291.     }
  292.  
  293.     /* Toggle INTR line of UART to create edge if multiple ints pending */
  294.     wrIER(0);
  295.     if (!errflag)
  296.         wrIER(IER_VAL2);
  297.  
  298.     outp(PICTRL, EOI);    /* send EOI to 8259A PIC */
  299.  
  300. }  /* end of serint() */
  301.  
  302.  
  303. /*
  304.  *    procarg(): process invocation arguments
  305.  */
  306.  
  307. void procarg(argc, argv)
  308.    int argc;
  309.    char **argv;
  310. {
  311.     int badarg = TRUE;        /* boolean: improper invocation arg. */
  312.  
  313.     switch (argc)
  314.     {
  315.     case 3:         /* baud rate divisor */
  316.         baudiv = atoi(argv[2]);
  317.         if (!MN_MX(baudiv, BAUDIV_MIN, BAUDIV_MAX))
  318.             break;
  319.     case 2:        /* COM number */
  320.         com = atoi(argv[1]);
  321.         if (!MN_MX(com, COM_MIN, COM_MAX))
  322.             break;
  323.     case 1:        /* no arguments => go with defaults */
  324.         badarg = FALSE;
  325.         break;
  326.     default:    /* illegal argument count */
  327.         break;
  328.     }
  329.  
  330.     if (badarg)
  331.         usage();        /* never returns */
  332.  
  333.     /* set up interrupt vector number and UART base address */
  334.     ivnum = comvnum[com-1];
  335.     ubase = uartbadd[com-1];
  336.  
  337.     /* verify existence of COM port */
  338.     savlcr = (UCHAR)inp(LCR);       /* save original LCR */
  339.     wrLCR(0x33);                    /* write test value to LCR */
  340.     if (inp(LCR) != 0x33)
  341.     {
  342.         printf("FATAL ERROR: COM%d not present\n", com);
  343.         exit(1);
  344.     }
  345.  
  346. }  /* end of procarg() */
  347.  
  348. /*
  349.  *    savepar(): save our environment parameters
  350.  */
  351.  
  352. void savepar()
  353. {
  354.     /* handle interrupt vector: save original and plug in our own address */
  355.     savect = _dos_getvect(ivnum);        /* save original int. vector */
  356.     _dos_setvect(ivnum, serint);
  357.  
  358.     /* handle ctrl-break/ctrl-c status: save original flag and disable it */
  359.     savbrk = GETBRK();
  360.     SETBRK(0);
  361.  
  362.     /* handle PIC mask: save original mask and allow COMx to interrupt */
  363.     savmsk = inp(PICMSK);
  364.     outp(PICMSK, inp(PICMSK) & picmsk[com-1]);
  365.  
  366.     /* save registers */
  367.     /* NOTE: LCR already saved in procarg() */
  368.     wrLCR(0x80);                    /* set DLAB */
  369.     savdll = (UCHAR)inp(DLL);    /* save baud */
  370.     savdlm = (UCHAR)inp(DLM);    /*   rate */
  371.     savier = (UCHAR)inp(IER);       /* save original IER */
  372.  
  373. }  /* end of savepar() */
  374.  
  375. /*****************************************************************************/
  376.  
  377. /*
  378.  *    rstrpar(): restore our environment parameters
  379.  */
  380.  
  381. void rstrpar()
  382. {
  383.     /* restore registers */
  384.     outp(LCR, 0x80);        /* set DLAB */
  385.     outp(DLL, savdll);        /* restore baud */
  386.     outp(DLM, savdlm);        /*   rate */
  387.     outp(LCR, 0);            /* clear DLAB */
  388.     outp(IER, savier);
  389.     outp(LCR, savlcr);
  390.  
  391.     /* restore original address to interrupt vector */
  392.     _dos_setvect(ivnum, savect);
  393.  
  394.     /* restore original ctrl-break/ctrl-c checking flag */
  395.     SETBRK(savbrk);
  396.  
  397.     /* restore original PIC mask */
  398.     outp(PICMSK, savmsk);
  399.  
  400. }  /* end of rstrpar() */
  401.  
  402.  
  403. /*****************************************************************************/
  404.  
  405. /*
  406.  *    usage(): display program usage information and terminate (never return)
  407.  */
  408.  
  409. void usage()
  410. {
  411.     printf("\n** HELP Screen for %s **\n\n", TESTNAME);
  412.     printf("USAGE: fact [<COM-number> [<baudrate-divisor>]]\n");
  413.     printf("                 arg1              arg2        \n");
  414.     printf(" ('fact' may be followed by no args, arg1, or arg1+2)\n\n");
  415.     printf("  ARGUMENT     MINIMUM VALUE    MAXIMUM VALUE    DEFAULT VALUE \n");
  416.     printf("============  ===============  ===============   ==============\n");
  417.     printf(" COM-number    %d (for COM%d)     %d (for COM%d)           %d  \n",
  418.     COM_MIN, COM_MIN, COM_MAX, COM_MAX, COM_DEF);
  419.     printf("              (serial line %d)  (serial line %d)      (COM%d)\n\n",
  420.     COM_MIN-1, COM_MAX-1, COM_DEF);
  421.     printf("  baudrate-   %d (56000 baud)   %d (%ld baud)       %4d        \n",
  422.     BAUDIV_MIN, BAUDIV_MAX, BAUDRATE(BAUDIV_MAX), BAUDIV_DEF);
  423.     printf("   divisor     (based on 1.8432 MHz crystal)      (%ld baud)   \n",
  424.     BAUDRATE(BAUDIV_DEF));
  425.     printf("    *  Sample baudrate divisors: for baud= 1200, use 96  *     \n");
  426.     printf("    *                                      2400      48  *     \n");
  427.     printf("    *                                      4800      24  *     \n");
  428.     printf("    *                                      9600      12  *     \n");
  429.     printf("    *                                     19200       6  *     \n");
  430.     exit(1);
  431.  
  432. }  /* end of usage() */
  433.  
  434. /* end of act.c */
  435.